package cn.lili.modules.search.serviceimpl;

import cn.lili.common.vo.PageVO;
import cn.lili.modules.lucene.GoodsAggregationService;
import cn.lili.modules.lucene.LuceneUtil;
import cn.lili.modules.lucene.SafeIndexAccessService;
import cn.lili.modules.search.entity.dos.EsGoodsIndex;
import cn.lili.modules.search.entity.dos.EsGoodsRelatedInfo;
import cn.lili.modules.search.entity.dto.EsGoodsSearchDTO;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.DoublePoint;
import org.apache.lucene.document.IntPoint;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.wltea.analyzer.lucene.IKAnalyzer;

import java.io.IOException;
import java.util.*;
import java.util.function.Function;

/**
 * @Author Sylow
 * @Description
 * @Date: Created in 17:02 2025/6/20
 */
@Service
public class GoodsSearchService {

//    @Autowired
//    private LuceneIndexManager indexManager;
    @Autowired
    private SafeIndexAccessService safeIndexAccessService;

    @Autowired
    private GoodsAggregationService goodsAggregationService;

    // 基本商品搜索 纯关键词搜索
    public List<Map<String, String>> search(String keyword, int pageSize, int pageNum) {
        int start = (pageNum - 1) * pageSize;

        Function<IndexSearcher, List<Map<String, String>>> searchOperation = searcher -> {
            try {
                // 创建多字段查询解析器
                MultiFieldQueryParser parser = new MultiFieldQueryParser(new String[]{"goodsName"}, new IKAnalyzer());
                Query query = parser.parse(QueryParser.escape(keyword));

                // 执行分页搜索
                TopDocs topDocs = searcher.search(query, start + pageSize);
                ScoreDoc[] scoreDocs = topDocs.scoreDocs;

                // 处理搜索结果
                List<Map<String, String>> results = new ArrayList<>();
                int end = Math.min(scoreDocs.length, start + pageSize);

                for (int i = start; i < end; i++) {
                    ScoreDoc scoreDoc = scoreDocs[i];
                    Document doc = searcher.doc(scoreDoc.doc);

                    Map<String, String> docMap = new HashMap<>();
                    docMap.put("id", doc.get("id")); // 假设文档有一个唯一标识字段"id"
                    docMap.put("goodsName", doc.get("goodsName"));


                    results.add(docMap);
                }

                return results;
            } catch (IOException | ParseException e) {
                throw new RuntimeException("搜索失败: " + e.getMessage(), e);
            }
        };

        return safeIndexAccessService.executeWithSearcher(searchOperation);
    }

    public Page<EsGoodsIndex> search(EsGoodsSearchDTO esGoodsSearchDTO, PageVO pageVo) {
        if (pageVo.getPageNumber() == 0) {
            pageVo.setPageNumber(pageVo.getPageNumber() + 1);
        }

        int start = (pageVo.getPageNumber() - 1) * pageVo.getPageSize();
        Function<IndexSearcher, Page<EsGoodsIndex>> searchOperation = searcher -> {
            try {
                // 构建主查询
                Query query = buildMainQuery(esGoodsSearchDTO);

                // 执行查询
                TopDocs topDocs = searcher.search(query, start + pageVo.getPageSize());
                ScoreDoc[] scoreDocs = topDocs.scoreDocs;

                // 计算分页范围
                int end = Math.min(scoreDocs.length, start + pageVo.getPageSize());

                // 转换结果集
                List<EsGoodsIndex> result = new ArrayList<>();
                for (int i = start; i < end; i++) {
                    Document doc = searcher.doc(scoreDocs[i].doc);
                    result.add(LuceneUtil.convertDocumentToEsGoodsIndex(doc));
                }

                Page<EsGoodsIndex> resultPage = new Page<>();
                resultPage.setRecords(result);
                resultPage.setCurrent(pageVo.getPageNumber());
                resultPage.setSize(pageVo.getPageSize());
                resultPage.setTotal(topDocs.totalHits.value);
                resultPage.setPages((long) Math.ceil((double) topDocs.totalHits.value / pageVo.getPageSize()));
                return resultPage;

            } catch (IOException | ParseException e) {
                throw new RuntimeException("搜索失败: " + e.getMessage(), e);
            }
        };

        return safeIndexAccessService.executeWithSearcher(searchOperation);
    }

    public EsGoodsRelatedInfo getSelector(EsGoodsSearchDTO esGoodsSearchDTO, PageVO pageVo) {
        Function<IndexSearcher, EsGoodsRelatedInfo> searchOperation = searcher -> {
            try {
                // 构建主查询
                Query query = buildMainQuery(esGoodsSearchDTO);

                EsGoodsRelatedInfo esGoodsRelatedInfo = goodsAggregationService.aggregateGoodsRelatedInfo(searcher, query);

                // 去掉已选择的属性
                String prop = esGoodsSearchDTO.getProp();
                if (prop != null && !prop.trim().isEmpty()) {
                    List<String> propList = Arrays.asList(prop.split("@"));
                    List<String> keyList = new ArrayList<>();
                    for (String propItem : propList) {
                        String[] parts = propItem.split("_");
                        if (parts.length == 2) {
                            String key = parts[0].trim();
                            keyList.add(key);
                        }
                    }
                    keyList = new ArrayList<>(new LinkedHashSet<>(keyList));

                    Set<String> keySet = new HashSet<>(keyList);
                    esGoodsRelatedInfo.getParamOptions().removeIf(propItem -> keySet.contains(propItem.getKey()));
                }

                return esGoodsRelatedInfo;
            } catch (Exception e) {
                throw new RuntimeException("获取筛选器失败: " + e.getMessage(), e);
            }
        };
        return safeIndexAccessService.executeWithSearcher(searchOperation);
    }

    private Query buildMainQuery(EsGoodsSearchDTO searchDTO) throws ParseException {
        BooleanQuery.Builder mainQuery = new BooleanQuery.Builder();

        // 1. 关键字查询
        if (!searchDTO.getKeyword().trim().isEmpty()) {
            String[] fields = {"goodsName"};
            MultiFieldQueryParser parser = new MultiFieldQueryParser(fields, new IKAnalyzer());
            parser.setDefaultOperator(QueryParser.Operator.OR);
            mainQuery.add(parser.parse(searchDTO.getKeyword()), BooleanClause.Occur.MUST);
        }

        // 2. 分类查询
        if (searchDTO.getCategoryId() != null && !searchDTO.getCategoryId().trim().isEmpty()) {
            mainQuery.add(new TermQuery(new Term("categoryPath", searchDTO.getCategoryId())), BooleanClause.Occur.MUST);
        }

        // 3. 品牌查询（多选）
        if (searchDTO.getBrandId() != null && !searchDTO.getBrandId().trim().isEmpty() ) {
            String[] brandIds = searchDTO.getBrandId().split("@");
            if (brandIds.length > 0) {
                BooleanQuery.Builder brandQuery = new BooleanQuery.Builder();
                for (String brandId : brandIds) {
                    brandQuery.add(new TermQuery(new Term("brandId", brandId)), BooleanClause.Occur.SHOULD);
                }
                mainQuery.add(brandQuery.build(), BooleanClause.Occur.MUST);
            }
        }

        // 4. 推荐商品
        if (searchDTO.getRecommend() != null) {
            int flag = searchDTO.getRecommend() ? 1 : 0;
            mainQuery.add(IntPoint.newExactQuery("recommend", flag), BooleanClause.Occur.MUST);
        }

        // 5. 价格区间
        if (searchDTO.getPrice() != null) {
            String[] priceRange = searchDTO.getPrice().split("_");
            if (priceRange.length == 2) {
                double min = Double.parseDouble(priceRange[0]);
                double max = Double.parseDouble(priceRange[1]);
                mainQuery.add(DoublePoint.newRangeQuery("priceIndex", min, max), BooleanClause.Occur.MUST);
            }
        }

        // 6. 属性查询（核心功能）
        if (searchDTO.getProp() != null && !searchDTO.getProp().isEmpty()) {
            mainQuery.add(buildAttributeQuery(searchDTO.getProp()), BooleanClause.Occur.MUST);
        }

        // 7. 店铺相关查询
        if (searchDTO.getStoreId() != null) {
            mainQuery.add(new TermQuery(new Term("storeId", searchDTO.getStoreId())), BooleanClause.Occur.MUST);
        }
        if (searchDTO.getStoreCatId() != null) {
            mainQuery.add(new TermQuery(new Term("storeCategoryPath", searchDTO.getStoreCatId())), BooleanClause.Occur.MUST);
        }

        // 8. 排除当前商品
        if (searchDTO.getCurrentGoodsId() != null) {
            mainQuery.add(new TermQuery(new Term("id", searchDTO.getCurrentGoodsId())), BooleanClause.Occur.MUST_NOT);
        }

        // 9. 其他字段查询...

        return mainQuery.build();
    }

    private Query buildAttributeQuery(String prop) {
        if (prop == null || prop.isEmpty()) {
            return null;
        }

        BooleanQuery.Builder attrQuery = new BooleanQuery.Builder();
        Map<String, Set<String>> conditionMap = new HashMap<>();

        // 解析属性条件：颜色_红@颜色_蓝@屏幕_6寸
        String[] pairs = prop.split("@");
        for (String pair : pairs) {
            String[] parts = pair.split("_", 2); // 只分割第一个下划线
            if (parts.length == 2) {
                String attrName = parts[0];
                String attrValue = parts[1];
                conditionMap.computeIfAbsent(attrName, k -> new HashSet<>())
                        .add(attrValue);
            }
        }

        // 构建属性查询
        for (Map.Entry<String, Set<String>> entry : conditionMap.entrySet()) {
            String attrName = entry.getKey();
            Set<String> values = entry.getValue();
            String fieldName = "attr_" + sanitizeFieldName(attrName);

            if (values.size() == 1) {
                // 单值精确匹配
                attrQuery.add(new TermQuery(new Term(fieldName, values.iterator().next())), BooleanClause.Occur.MUST);
            } else {
                // 多值OR关系
                BooleanQuery.Builder orQuery = new BooleanQuery.Builder();
                for (String value : values) {
                    orQuery.add(new TermQuery(new Term(fieldName, value)), BooleanClause.Occur.SHOULD);
                }
                attrQuery.add(orQuery.build(), BooleanClause.Occur.MUST);
            }
        }
        return attrQuery.build();
    }



    private String sanitizeFieldName(String name) {
        return name.replaceAll("[^a-zA-Z0-9_]", "_");
    }
}